#include "MarioMap.h"
#include "BrickEx.h"
#include "Turtle.h"
#include "Grass.h"
#include "Fence.h"
#include "Goomba.h"
#include "Pipe.h"
#include "Piranha.h"
#include "Question.h"
#include "Stone.h"
#include "Coin.h"
#include "Canon.h"
#include "Flower.h"
#include "Star.h"
#include "EndPoint.h"

MarioMap::MarioMap()
{
	
}
std::vector<std::string>& MarioMap::split(const std::string &s, char delim, std::vector<std::string> &elems)
{
	std::stringstream ss(s);
	std::string item;
	while(std::getline(ss, item, delim))
	{
		elems.push_back(item);
	}
	return elems;
}

std::vector<std::string> MarioMap::split(const std::string &s, char delim)
{
	std::vector<std::string> elems;
	return split(s, delim, elems);
}

void MarioMap ::LoadObjectFromFile(std::string fileName)
{
	list<Object*> ans;
	string data;
	ifstream fileStream(fileName);
	if (fileStream.is_open())
	{
		while (!fileStream.eof())
		{
			data += fileStream.get();
		}
	}
	vector<string> dataSplit = split(data, '\n');
	width_map =  atoi(dataSplit[0].c_str());
	height_map =  atoi(dataSplit[1].c_str());
	for(int i = 2;i<dataSplit.size()-1;i++)
	{
		int test = dataSplit.size();
		string temp = dataSplit[i];
		vector<string> temp_vector = split(temp,' ');
		float tempX = atoi(temp_vector[1].c_str());
		float tempY = atoi(temp_vector[2].c_str());
		int tempType = atoi(temp_vector[0].c_str());
		int tempID = atoi(temp_vector[4].c_str());
		
		if(tempType == 75)
		{
			EndPoint *endpoint = new EndPoint(tempID,tempX,tempY,tempType);
			_listObject.push_back(endpoint);
		}
		if(tempType == 1)
		{
			BrickEx *brick = new BrickEx(tempID,tempX,tempY,BS_NORMAL,tempType);
			_listObject.push_back(brick);
		}
		if(tempType == 2 || tempType == 56)
		{	
			Stone *stone = new Stone(tempID,tempX,tempY,tempType);
			_listObject.push_back(stone);
		}
		if(tempType == 3 || tempType == 4 || tempType == 5 ||tempType == 42 || tempType == 43 || tempType == 44
			||tempType == 61 || tempType == 62 || tempType == 63 )
		{	
			Grass *grass = new Grass(tempID,tempX,tempY,tempType);
			_listObject.push_back(grass);
		}
		if(tempType == 6)
		{	
			Question *question = new Question(tempID,tempX,tempY,tempType,BS_NORMAL);
			_listObject.push_back(question);
		}
		if(tempType == 15 || tempType == 16 || tempType == 17)
		{	
			Flower *flower = new Flower(tempID,tempX,tempY,tempType,IS_IDLE);
			_listObject.push_back(flower);
		}
		if(tempType == 18)
		{	
			Star *star = new Star(tempID,tempX,tempY,tempType,IS_IDLE);
			_listObject.push_back(star);
		}
		
		if(tempType == 14|| tempType == 39)
		{	
			Coin *coin = new Coin(tempID,tempX,tempY,tempType, IS_IDLE);
			_listObject.push_back(coin);
		}
		if(tempType == 8)
		{	
			Canon *canon = new Canon(tempID,tempX,tempY,tempType,BS_NORMAL);
			_listObject.push_back(canon);
		}
		if(tempType == 9)
		{
			Goomba *goomba = new Goomba(tempID,tempX,tempY,tempType,ES_ACTIVING,1);
			_listObject.push_back(goomba);
		}
		if(tempType == 11)
		{	
			Piranha *piranha = new Piranha(tempID,tempX,tempY,tempType,BS_NORMAL);
			_listObject.push_back(piranha);
		}
		if(tempType == 12)
		{	
			Turtle *turtle = new Turtle(tempID,tempX,tempY,tempType,ES_ACTIVING,1);
			_listObject.push_back(turtle);
		}
		if(tempType == 21 || tempType == 22 || tempType == 23 || tempType == 19 || tempType == 20
			||tempType == 24 || tempType == 25 || tempType == 26 || tempType == 27 || tempType == 28
			||tempType == 35 || tempType == 36 || tempType == 37 || tempType == 45 || tempType == 46 
			||tempType == 47 || tempType == 57 || tempType == 58 || tempType == 59 || tempType == 71
			||tempType == 72 || tempType == 73 || tempType == 74)
		{	
			Fence *fence = new Fence(tempID,tempX,tempY,tempType);
			_listObject.push_back(fence);
		}
		
		if(tempType == 29 || tempType == 30 || tempType == 31 || tempType == 32 ||tempType == 33 ||tempType == 34 
			|| tempType == 64 || tempType == 65 || tempType == 66 || tempType == 67 ||tempType == 68 ||tempType == 69 
			|| tempType == 48 || tempType == 49 || tempType == 50 || tempType == 51 ||tempType == 52 ||tempType == 53 )
		{	
			Pipe *pipe = new Pipe(tempID,tempX,tempY,tempType,BS_NORMAL);
			_listObject.push_back(pipe);
		}
	}
}

void MarioMap :: LoadMapFromFile(std::string fileName)
{
	string data;
	ifstream fileStream(fileName);
	if (fileStream.is_open())
	{
		while (!fileStream.eof())
		{
			data += fileStream.get();
		}
	}
	vector<string> dataSplit = split(data, '\n');

	for (int i = 0; i < dataSplit.size() - 1; i++)
	{
		string temp = dataSplit[i];
		vector<string> temp_vector = split(temp, ' ');

		int _id = atoi(temp_vector[0].c_str());
		int _x1 =  atoi(temp_vector[1].c_str());
		int _y1 =  atoi(temp_vector[2].c_str());
		int _x2 =  atoi(temp_vector[3].c_str());
		int _y2 =  atoi(temp_vector[4].c_str());

		//tao Node
		Node *n;
		n = new Node(_id, _x1, _y1,_x2, _y2);


		if (temp_vector.size() >= 5)
		{
			for (int j = 5; j < temp_vector.size(); j++)
			{
				//add cac id object vao node
				int _idObj = atoi(temp_vector[j].c_str());

				Object *_obj;
				list<Object*>::iterator k;
				for (k = this->_listObject.begin(); k != this->_listObject.end(); k++)
				{
					_obj = *k;
					if (_idObj == _obj->getIDObj())
					{
						n->addGameObject(_obj);
					}

				}
			}
		}

		_mapQuadTree[n->getIDNode()] = n;

	}
}



void MarioMap::Deserialize(QuadTree *root)
{
	Node *node = (Node*) _mapQuadTree[0];
	
	root->setRoot(node);
	//q_tree->setRoot(p_qnode);
	Build(root->getRoot());

}

void MarioMap::Build(Node *n)
{
	int id_node = n->getIDNode();

	if (!_mapQuadTree[id_node * 4 + 1])
	{
		return;
	}


	if (_mapQuadTree[id_node * 4 + 1])
	{
		n->setLeftTop(_mapQuadTree[id_node * 4 + 1]);
	}
	
	if (_mapQuadTree[id_node * 4 + 3])
	{
		n->setRightTop(_mapQuadTree[id_node * 4 + 3]);
		
	}
	
	if (_mapQuadTree[id_node * 4 + 2])
	{
		n->setLeftBottom(_mapQuadTree[id_node * 4 + 2]);
		
	}
	
	if (_mapQuadTree[id_node * 4 + 4])
	{
		n->setRightBottom(_mapQuadTree[id_node * 4 + 4]);
		
	}
	
	 
	Build(n->getLeftTop());
	Build(n->getRightTop());
	Build(n->getLeftBottom());
	Build(n->getRightBottom());
}
